const User = require('../models/User');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const db = require('../config/database');
const { logger } = require('../utils/logger');

/**
 * 用户认证控制器
 * 处理用户注册、登录、密码重置等认证相关功能
 */
class AuthController {
  /**
   * 用户注册
   * POST /api/auth/register
   */
  static async register(req, res) {
    try {
      const {
        email,
        password,
        username,
        first_name,
        last_name,
        phone,
        date_of_birth,
        gender,
        preferred_language
      } = req.body;

      // 创建新用户
      const newUser = await User.create({
        email,
        password,
        username,
        first_name,
        last_name,
        phone,
        date_of_birth,
        gender,
        preferred_language
      });

      // 生成JWT令牌
      const token = newUser.generateToken();

      // 发送欢迎邮件（异步处理，不阻塞响应）
      AuthController.sendWelcomeEmail(newUser.email, newUser.first_name || newUser.username)
        .catch(error => logger.error('发送欢迎邮件失败:', error));

      // 返回成功响应
      res.status(201).json({
        success: true,
        message: '用户注册成功',
        data: {
          user: newUser.toSafeObject(),
          token,
          token_type: 'Bearer',
          expires_in: process.env.JWT_EXPIRES_IN || '7d'
        }
      });
    } catch (error) {
      logger.error('用户注册失败:', error);
      
      // 处理特定错误
      if (error.message.includes('已被注册') || error.message.includes('已被使用')) {
        return res.status(409).json({
          success: false,
          message: error.message,
          error_code: 'DUPLICATE_USER'
        });
      }
      
      res.status(500).json({
        success: false,
        message: '注册过程中发生错误，请稍后重试',
        error_code: 'REGISTRATION_ERROR'
      });
    }
  }

  /**
   * 用户登录
   * POST /api/auth/login
   */
  static async login(req, res) {
    try {
      const { email, password, remember_me = false } = req.body;

      // 查找用户
      const user = await User.findByEmail(email);
      if (!user) {
        return res.status(401).json({
          success: false,
          message: '邮箱或密码错误',
          error_code: 'INVALID_CREDENTIALS'
        });
      }

      // 验证密码
      const isPasswordValid = await user.validatePassword(password);
      if (!isPasswordValid) {
        return res.status(401).json({
          success: false,
          message: '邮箱或密码错误',
          error_code: 'INVALID_CREDENTIALS'
        });
      }

      // 更新最后登录时间
      await user.updateLastLogin();

      // 生成JWT令牌
      const token = user.generateToken();

      // 设置令牌过期时间（如果选择记住我，延长过期时间）
      const expiresIn = remember_me ? '30d' : (process.env.JWT_EXPIRES_IN || '7d');

      res.json({
        success: true,
        message: '登录成功',
        data: {
          user: user.toSafeObject(),
          token,
          token_type: 'Bearer',
          expires_in: expiresIn
        }
      });
    } catch (error) {
      logger.error('用户登录失败:', error);
      res.status(500).json({
        success: false,
        message: '登录过程中发生错误，请稍后重试',
        error_code: 'LOGIN_ERROR'
      });
    }
  }

  /**
   * 获取当前用户信息
   * GET /api/auth/me
   */
  static async getCurrentUser(req, res) {
    try {
      // 用户信息已在认证中间件中设置
      res.json({
        success: true,
        message: '获取用户信息成功',
        data: {
          user: req.user.toSafeObject()
        }
      });
    } catch (error) {
      logger.error('获取用户信息失败:', error);
      res.status(500).json({
        success: false,
        message: '获取用户信息失败',
        error_code: 'GET_USER_ERROR'
      });
    }
  }

  /**
   * 刷新令牌
   * POST /api/auth/refresh
   */
  static async refreshToken(req, res) {
    try {
      // 用户信息已在认证中间件中验证
      const user = req.user;
      
      // 生成新的JWT令牌
      const newToken = user.generateToken();

      res.json({
        success: true,
        message: '令牌刷新成功',
        data: {
          token: newToken,
          token_type: 'Bearer',
          expires_in: process.env.JWT_EXPIRES_IN || '7d'
        }
      });
    } catch (error) {
      logger.error('令牌刷新失败:', error);
      res.status(500).json({
        success: false,
        message: '令牌刷新失败',
        error_code: 'TOKEN_REFRESH_ERROR'
      });
    }
  }

  /**
   * 用户登出
   * POST /api/auth/logout
   */
  static async logout(req, res) {
    try {
      // 在实际应用中，可以将令牌加入黑名单
      // 这里简单返回成功响应，客户端需要删除本地存储的令牌
      
      res.json({
        success: true,
        message: '登出成功'
      });
    } catch (error) {
      logger.error('用户登出失败:', error);
      res.status(500).json({
        success: false,
        message: '登出过程中发生错误',
        error_code: 'LOGOUT_ERROR'
      });
    }
  }

  /**
   * 请求密码重置
   * POST /api/auth/forgot-password
   */
  static async forgotPassword(req, res) {
    try {
      const { email } = req.body;

      // 查找用户
      const user = await User.findByEmail(email);
      if (!user) {
        // 为了安全，即使用户不存在也返回成功消息
        return res.json({
          success: true,
          message: '如果该邮箱已注册，您将收到密码重置邮件'
        });
      }

      // 生成重置令牌
      const resetToken = crypto.randomBytes(32).toString('hex');
      const resetTokenExpiry = new Date(Date.now() + 3600000); // 1小时后过期

      // 存储重置令牌到数据库
      const sql = `
        INSERT INTO password_reset_tokens (user_id, token, expires_at, created_at)
        VALUES (?, ?, ?, NOW())
        ON DUPLICATE KEY UPDATE
        token = VALUES(token),
        expires_at = VALUES(expires_at),
        created_at = NOW()
      `;
      
      await db.execute(sql, [user.user_id, resetToken, resetTokenExpiry]);

      // 发送重置邮件
      await AuthController.sendPasswordResetEmail(user.email, resetToken, user.first_name || user.username);

      res.json({
        success: true,
        message: '密码重置邮件已发送，请检查您的邮箱'
      });
    } catch (error) {
      logger.error('密码重置请求失败:', error);
      res.status(500).json({
        success: false,
        message: '发送密码重置邮件失败，请稍后重试',
        error_code: 'PASSWORD_RESET_REQUEST_ERROR'
      });
    }
  }

  /**
   * 重置密码
   * POST /api/auth/reset-password
   */
  static async resetPassword(req, res) {
    try {
      const { token, new_password } = req.body;

      // 验证重置令牌
      const sql = `
        SELECT prt.user_id, prt.expires_at
        FROM password_reset_tokens prt
        WHERE prt.token = ? AND prt.expires_at > NOW()
      `;
      
      const [tokenRows] = await db.execute(sql, [token]);
      
      if (tokenRows.length === 0) {
        return res.status(400).json({
          success: false,
          message: '重置令牌无效或已过期',
          error_code: 'INVALID_RESET_TOKEN'
        });
      }

      const userId = tokenRows[0].user_id;
      
      // 获取用户信息
      const user = await User.findById(userId);
      if (!user) {
        return res.status(404).json({
          success: false,
          message: '用户不存在',
          error_code: 'USER_NOT_FOUND'
        });
      }

      // 更新密码
      await user.updatePassword(new_password);

      // 删除使用过的重置令牌
      await db.execute('DELETE FROM password_reset_tokens WHERE token = ?', [token]);

      res.json({
        success: true,
        message: '密码重置成功，请使用新密码登录'
      });
    } catch (error) {
      logger.error('密码重置失败:', error);
      res.status(500).json({
        success: false,
        message: '密码重置失败，请稍后重试',
        error_code: 'PASSWORD_RESET_ERROR'
      });
    }
  }

  /**
   * 更改密码
   * POST /api/auth/change-password
   */
  static async changePassword(req, res) {
    try {
      const { current_password, new_password } = req.body;
      const user = req.user;

      // 验证当前密码
      const isCurrentPasswordValid = await user.validatePassword(current_password);
      if (!isCurrentPasswordValid) {
        return res.status(400).json({
          success: false,
          message: '当前密码错误',
          error_code: 'INVALID_CURRENT_PASSWORD'
        });
      }

      // 更新密码
      await user.updatePassword(new_password);

      res.json({
        success: true,
        message: '密码更改成功'
      });
    } catch (error) {
      logger.error('更改密码失败:', error);
      res.status(500).json({
        success: false,
        message: '更改密码失败，请稍后重试',
        error_code: 'CHANGE_PASSWORD_ERROR'
      });
    }
  }

  /**
   * 发送邮箱验证码
   * POST /api/auth/send-email-verification
   */
  static async sendEmailVerification(req, res) {
    try {
      const user = req.user;
      
      if (user.email_verified) {
        return res.status(400).json({
          success: false,
          message: '邮箱已经验证过了',
          error_code: 'EMAIL_ALREADY_VERIFIED'
        });
      }

      // 生成6位数验证码
      const verificationCode = Math.floor(100000 + Math.random() * 900000).toString();
      const expiresAt = new Date(Date.now() + 600000); // 10分钟后过期

      // 存储验证码
      const sql = `
        INSERT INTO email_verification_codes (user_id, code, expires_at, created_at)
        VALUES (?, ?, ?, NOW())
        ON DUPLICATE KEY UPDATE
        code = VALUES(code),
        expires_at = VALUES(expires_at),
        created_at = NOW()
      `;
      
      await db.execute(sql, [user.user_id, verificationCode, expiresAt]);

      // 发送验证邮件
      await AuthController.sendEmailVerificationCode(user.email, verificationCode, user.first_name || user.username);

      res.json({
        success: true,
        message: '验证码已发送到您的邮箱，请在10分钟内完成验证'
      });
    } catch (error) {
      logger.error('发送邮箱验证码失败:', error);
      res.status(500).json({
        success: false,
        message: '发送验证码失败，请稍后重试',
        error_code: 'SEND_VERIFICATION_ERROR'
      });
    }
  }

  /**
   * 发送手机验证码
   * POST /api/auth/send-phone-verification
   */
  static async sendPhoneVerification(req, res) {
    try {
      const user = req.user;
      
      if (!user.phone) {
        return res.status(400).json({
          success: false,
          message: '用户未绑定手机号',
          error_code: 'NO_PHONE_NUMBER'
        });
      }

      if (user.phone_verified) {
        return res.status(400).json({
          success: false,
          message: '手机号已经验证过了',
          error_code: 'PHONE_ALREADY_VERIFIED'
        });
      }

      // 生成6位数验证码
      const verificationCode = Math.floor(100000 + Math.random() * 900000).toString();
      const expiresAt = new Date(Date.now() + 600000); // 10分钟后过期

      // 存储验证码
      const sql = `
        INSERT INTO phone_verification_codes (user_id, code, expires_at, created_at)
        VALUES (?, ?, ?, NOW())
        ON DUPLICATE KEY UPDATE
        code = VALUES(code),
        expires_at = VALUES(expires_at),
        created_at = NOW()
      `;
      
      await db.execute(sql, [user.user_id, verificationCode, expiresAt]);

      // TODO: 集成短信服务发送验证码
      // 暂时返回成功，实际项目中需要集成阿里云短信、腾讯云短信等服务
      // 开发环境日志（不包含完整手机号与验证码）
      if (process.env.NODE_ENV === 'development') {
        const tail = String(user.phone || '').slice(-4);
        logger.debug(`手机验证码已生成，手机号尾号 ****${tail}`);
      }

      res.json({
        success: true,
        message: '验证码已发送到您的手机，请在10分钟内完成验证',
        // 开发环境下返回验证码，生产环境需要删除
        ...(process.env.NODE_ENV === 'development' && { verification_code: verificationCode })
      });
    } catch (error) {
      logger.error('发送手机验证码失败:', error);
      res.status(500).json({
        success: false,
        message: '发送验证码失败，请稍后重试',
        error_code: 'SEND_VERIFICATION_ERROR'
      });
    }
  }

  /**
   * 验证邮箱
   * POST /api/auth/verify-email
   */
  static async verifyEmail(req, res) {
    try {
      const { verification_code } = req.body;
      const user = req.user;

      // 验证验证码
      const sql = `
        SELECT code FROM email_verification_codes
        WHERE user_id = ? AND code = ? AND expires_at > NOW()
      `;
      
      const [codeRows] = await db.execute(sql, [user.user_id, verification_code]);
      
      if (codeRows.length === 0) {
        return res.status(400).json({
          success: false,
          message: '验证码无效或已过期',
          error_code: 'INVALID_VERIFICATION_CODE'
        });
      }

      // 标记邮箱为已验证
      await user.verifyEmail();

      // 删除使用过的验证码
      await db.execute('DELETE FROM email_verification_codes WHERE user_id = ?', [user.user_id]);

      res.json({
        success: true,
        message: '邮箱验证成功'
      });
    } catch (error) {
      logger.error('邮箱验证失败:', error);
      res.status(500).json({
        success: false,
        message: '邮箱验证失败，请稍后重试',
        error_code: 'EMAIL_VERIFICATION_ERROR'
      });
    }
  }

  /**
   * 验证手机号
   * POST /api/auth/verify-phone
   */
  static async verifyPhone(req, res) {
    try {
      const { verification_code } = req.body;
      const user = req.user;

      // 验证验证码
      const sql = `
        SELECT code FROM phone_verification_codes
        WHERE user_id = ? AND code = ? AND expires_at > NOW()
      `;
      
      const [codeRows] = await db.execute(sql, [user.user_id, verification_code]);
      
      if (codeRows.length === 0) {
        return res.status(400).json({
          success: false,
          message: '验证码无效或已过期',
          error_code: 'INVALID_VERIFICATION_CODE'
        });
      }

      // 标记手机号为已验证
      await user.verifyPhone();

      // 删除使用过的验证码
      await db.execute('DELETE FROM phone_verification_codes WHERE user_id = ?', [user.user_id]);

      res.json({
        success: true,
        message: '手机号验证成功'
      });
    } catch (error) {
      logger.error('手机号验证失败:', error);
      res.status(500).json({
        success: false,
        message: '手机号验证失败，请稍后重试',
        error_code: 'PHONE_VERIFICATION_ERROR'
      });
    }
  }

  /**
   * 发送欢迎邮件
   * @param {string} email - 邮箱地址
   * @param {string} name - 用户名
   */
  static async sendWelcomeEmail(email, name) {
    try {
      const transporter = nodemailer.createTransporter({
        host: process.env.SMTP_HOST,
        port: process.env.SMTP_PORT,
        secure: process.env.SMTP_SECURE === 'true',
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASS
        }
      });

      const mailOptions = {
        from: `"CU MR BULL" <${process.env.SMTP_FROM}>`,
        to: email,
        subject: '欢迎加入 CU MR BULL！',
        html: `
          <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
            <h2 style="color: #d32f2f;">欢迎加入 CU MR BULL！</h2>
            <p>亲爱的 ${name}，</p>
            <p>感谢您注册 CU MR BULL 账户！我们很高兴您加入我们的韩式美食大家庭。</p>
            <p>现在您可以：</p>
            <ul>
              <li>浏览我们精选的韩式料理菜单</li>
              <li>享受会员专属优惠和积分奖励</li>
              <li>在线预订和外卖服务</li>
              <li>参与我们的会员活动</li>
            </ul>
            <p>如果您有任何问题，请随时联系我们的客服团队。</p>
            <p>祝您用餐愉快！</p>
            <p><strong>CU MR BULL 团队</strong></p>
          </div>
        `
      };

      await transporter.sendMail(mailOptions);
    } catch (error) {
      logger.error('发送欢迎邮件失败:', error);
      throw error;
    }
  }

  /**
   * 发送密码重置邮件
   * @param {string} email - 邮箱地址
   * @param {string} resetToken - 重置令牌
   * @param {string} name - 用户名
   */
  static async sendPasswordResetEmail(email, resetToken, name) {
    try {
      const transporter = nodemailer.createTransporter({
        host: process.env.SMTP_HOST,
        port: process.env.SMTP_PORT,
        secure: process.env.SMTP_SECURE === 'true',
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASS
        }
      });

      const resetUrl = `${process.env.FRONTEND_URL}/reset-password?token=${resetToken}`;

      const mailOptions = {
        from: `"CU MR BULL" <${process.env.SMTP_FROM}>`,
        to: email,
        subject: 'CU MR BULL - 密码重置请求',
        html: `
          <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
            <h2 style="color: #d32f2f;">密码重置请求</h2>
            <p>亲爱的 ${name}，</p>
            <p>我们收到了您的密码重置请求。请点击下面的链接重置您的密码：</p>
            <p style="margin: 20px 0;">
              <a href="${resetUrl}" style="background-color: #d32f2f; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block;">重置密码</a>
            </p>
            <p>此链接将在1小时后过期。如果您没有请求重置密码，请忽略此邮件。</p>
            <p>如果按钮无法点击，请复制以下链接到浏览器：</p>
            <p style="word-break: break-all; color: #666;">${resetUrl}</p>
            <p><strong>CU MR BULL 团队</strong></p>
          </div>
        `
      };

      await transporter.sendMail(mailOptions);
    } catch (error) {
      logger.error('发送密码重置邮件失败:', error);
      throw error;
    }
  }

  /**
   * 发送邮箱验证码
   * @param {string} email - 邮箱地址
   * @param {string} verificationCode - 验证码
   * @param {string} name - 用户名
   */
  static async sendEmailVerificationCode(email, verificationCode, name) {
    try {
      const transporter = nodemailer.createTransporter({
        host: process.env.SMTP_HOST,
        port: process.env.SMTP_PORT,
        secure: process.env.SMTP_SECURE === 'true',
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASS
        }
      });

      const mailOptions = {
        from: `"CU MR BULL" <${process.env.SMTP_FROM}>`,
        to: email,
        subject: 'CU MR BULL - 邮箱验证码',
        html: `
          <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
            <h2 style="color: #d32f2f;">邮箱验证</h2>
            <p>亲爱的 ${name}，</p>
            <p>您的邮箱验证码是：</p>
            <p style="font-size: 32px; font-weight: bold; color: #d32f2f; text-align: center; margin: 20px 0; padding: 20px; background-color: #f5f5f5; border-radius: 8px;">${verificationCode}</p>
            <p>此验证码将在10分钟后过期，请尽快完成验证。</p>
            <p>如果您没有请求此验证码，请忽略此邮件。</p>
            <p><strong>CU MR BULL 团队</strong></p>
          </div>
        `
      };

      await transporter.sendMail(mailOptions);
    } catch (error) {
      logger.error('发送邮箱验证码失败:', error);
      throw error;
    }
  }
}

module.exports = AuthController;